package com.ruoyi.common.utils.sign;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSAEncryptionDecryption {

    public static void main(String[] args) {
        try {
            // 示例公钥和私钥（Base64编码）
            String publicKeyString = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkHSlTLBCd2lTvciho8IXCF6qATkzPC5oNssC0C71hrigKn9XJaeyE/M/MmLfmgmMAodArtx00JvDt6kqhPVWLtFvZ1bebdLBSIN5+cCwRvH0yIqA4qQZ/zHBDve33Tsv79THcUJhMqyyUSGWWQXagwNWehLH41V4L7jr9tO6qVPJQMjHUFJQnDG7N6HwNDHDhRT51BBmglFTh0k11K5zASlcnSNiMckY3e7XVvv0ZzIL4Axo5J4lSJ4FARy3ly02BfBfj3s5bkJB8SndvihwoNIlcTevHbj03l+xgwnAuFku6VSYD7gta7y67OUd2bZLAv99ov3cUhi1Y1lkXj7WgQIDAQAB";
            String privateKeyString = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCQdKVMsEJ3aVO9yKGjwhcIXqoBOTM8Lmg2ywLQLvWGuKAqf1clp7IT8z8yYt+aCYwCh0Cu3HTQm8O3qSqE9VYu0W9nVt5t0sFIg3n5wLBG8fTIioDipBn/McEO97fdOy/v1MdxQmEyrLJRIZZZBdqDA1Z6EsfjVXgvuOv207qpU8lAyMdQUlCcMbs3ofA0McOFFPnUEGaCUVOHSTXUrnMBKVydI2IxyRjd7tdW+/RnMgvgDGjkniVIngUBHLeXLTYF8F+PezluQkHxKd2+KHCg0iVxN68duPTeX7GDCcC4WS7pVJgPuC1rvLrs5R3ZtksC/32i/dxSGLVjWWRePtaBAgMBAAECggEAFcRd5tEQfZSIzSo0S8wX/bzgpSU3YTQk+Uyx9H4ppSP2OTEjB/Ddq+qVdUQ3fqs9m7aXD+z29Trjd64CqDJHyu+SzTbmdr9b509YdpfgeBrxewkpI/2npS/xcA3yeLWjIuJ52HPbgu/0QWFsRFHWJrO+uM+nqyEv5mZZDW0YzXbb95mdu/zXxBNOQKxzoZ4Ha9KjSLINXM0Xpz0ME+kr48cQDMeYXeCKCv/qM2GyyUF5jfYmONG8CUEIx2jBlo4cfB2W/d8yZqGXXGeKJfgHogJHbdC9Jc5ximnYPVECgaQ0hhbFr8wkmncLNYSNKlKy/ltHcG3YAblahbizWe5K+QKBgQC5Lo4/Z793YPhoGXomxreE6VxEDWeN33iC3ri+7sc2moNmVyjVTXbzMkTIJ58c+FoihslwNrMGy3HroU16/FJrtaKryGOj0uVh7n9heReoQ7Tl/F/Z2pF6VUNOg4q09uvzrQVjz5g21p0MGJwwexjHRopGZHZtoxH4nmjMpLL3vwKBgQDHsvaPb71IVOCbaNAtBc+XX4JUQMZhPxUv39Tm7jNrsd60I4cByNYL3O/LzZDWzanisUCmnbV84CLwUVbS2y+9T8h682YJw7MPqEZAicq7NgY+H40vFKQvoUUajkzzHJa0RZuu6+VvgctR8MoPDAt7K+LKKsbhiNlzrDHW5E/BvwKBgCA2QPg2i8+wRoWVKPJlzraIAUy1KDY9kTDynSBZWL3e0sySjL/N4cscC2rluX/Ik6U93PxwB2Q/L2nVfSzPh2bFCa7oBK0SmmQWoIHMFplmbakz5Vh39KZa/oJBz3b7HMAecLmT+t5PJrJb9Y9ZWk4Pry3fe9pGa3Hb3E78t0TxAoGAW6kQNLwkFEwpIAwW6WNualuDVaq5o68xyVyiuzCAV6E3yFU6RZ5qaN2LD2+WWJHjtVKIizF+OQgj4UxkXroOioVRTuXjYv35dWlWfY8Bh7Z/XQpcYkzGI7qRHmRMe5YWsj30/G/4Sps3uK+d/xQXPPzixsqlqKWIsehKpAj9dr8CgYAe1imkzsCLUSZy17o6nMhDLLdOkJeMQu3rKw32DOtBQZiufA870r0pHPeoshI1wOZK0Mupyweqj+Mv6dLJUkTCBfiJyzrqqdkvs6nd0f9IifV05t9M9jA8Rktbl9MpvX9grbQ0COv32qg3+DPxAT4UhAYImdRV0bVxv089cQ3KVA==";

            // 将Base64编码的公钥和私钥转换为PublicKey和PrivateKey对象
            PublicKey publicKey = getPublicKeyFromBase64(publicKeyString);
            PrivateKey privateKey = getPrivateKeyFromBase64(privateKeyString);

            // 要加密的数据
            String originalData = "{\n" +
                    "    \"tenantId\": \"1\",\n" +
                    "    \"outOrderId\": \"2GbRfo4tDn\",\n" +
                    "    \"outOrderNo\": \"vsjX4WAibx"+System.currentTimeMillis()+"\"," +
                    "    \"productName\": \"Orange premium\",\n" +
                    "    \"productInfo\": \"{\\\"key5\\\": 490, \\\"key8\\\": 64, \\\"key91\\\": 80, \\\"key98\\\": 96, \\\"key876\\\": 978}\",\n" +
                    "    \"customerName\": \"Chin Kwok Yin\",\n" +
                    "    \"mobile\": \"PwT88jOWIo\",\n" +
                    "    \"address\": \"3-19-8 Shimizu, Kita Ward\",\n" +
                    "    \"idCard\": \"mM8SUeoweZ\",\n" +
                    "    \"idCardFront\": \"HAuLWSer9I\",\n" +
                    "    \"idCardBack\": \"j2ZpXqswHE\",\n" +
                    "    \"totalAmount\": 41.17,\n" +
                    "    \"repaidAmount\": 364.12,\n" +
                    "    \"unpaidAmount\": 284.89,\n" +
                    "    \"totalPeriods\": 589,\n" +
                    "    \"repaidPeriods\": 359,\n" +
                    "    \"unpaidPeriods\": 645,\n" +
                    "    \"repaymentPlan\": \"{\\\"key3\\\": 17, \\\"key46\\\": 1, \\\"key76\\\": 12, \\\"key115\\\": 9, \\\"key588\\\": 15}\",\n" +
                    "    \"contractUrl\": \"https://auth.sano225.xyz/Beauty\",\n" +
                    "    \"riskReportUrl\": \"http://image.matsuren.cn/ToysGames\",\n" +
                    "    \"orderStatus\": 0,\n" +
                    "    \"overdueDays\": 4,\n" +
                    "    \"userId\": 365,\n" +
                    "    \"collectionStatus\": 0,\n" +
                    "    \"collectionTimes\": 333,\n" +
                    "    \"lastCollectionTime\": \"2023-05-12T00:24:31.000+08:00\",\n" +
                    "    \"settlementAmount\": 487.66,\n" +
                    "    \"collectionRemark\": \"gXWEm168wv\",\n" +
                    "    \"createDept\": 930,\n" +
                    "    \"delFlag\": \"0\",\n" +
                    "    \"createBy\": \"JeXJiEY6c6\",\n" +
                    "    \"createTime\": \"2023-12-30T01:11:25.000+08:00\",\n" +
                    "    \"updateBy\": \"2004-07-12\",\n" +
                    "    \"updateTime\": \"2017-05-19T13:19:49.000+08:00\",\n" +
                    "    \"remark\": \"sco6PRxMgE\"\n" +
                    "}";

            System.out.println("Original Data: " + originalData);

            // 使用私钥加密数据
            String encryptedData = encrypt(originalData, privateKeyString);
            System.out.println("Encrypted Data: " + encryptedData);

            // 使用公钥解密数据
            String decryptedData = decrypt(encryptedData, publicKeyString);
            System.out.println("Decrypted Data: " + decryptedData);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static PublicKey getPublicKeyFromBase64(String base64PublicKey) throws Exception {
        byte[] decodedKey = Base64.getDecoder().decode(base64PublicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }

    private static PrivateKey getPrivateKeyFromBase64(String base64PrivateKey) throws Exception {
        byte[] decodedKey = Base64.getDecoder().decode(base64PrivateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }



    public static String encrypt(String data, String privateKeyString) throws Exception {
        PrivateKey publicKey = getPrivateKeyFromBase64(privateKeyString);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] dataBytes = data.getBytes();
        int inputLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > 245) {
                cache = cipher.doFinal(dataBytes, offSet, 245);
            } else {
                cache = cipher.doFinal(dataBytes, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * 245;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    // 解密方法也需要相应地进行分段处理
    public static String decrypt(String encryptedData, String publicKeyString) throws Exception {

        PublicKey privateKey = getPublicKeyFromBase64(publicKeyString);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
        int inputLen = encryptedBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > 256) {
                cache = cipher.doFinal(encryptedBytes, offSet, 256);
            } else {
                cache = cipher.doFinal(encryptedBytes, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * 256;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return new String(decryptedData);
    }
}


